﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace LuaNet
{
    class LuaCFunctionProxy
    {
        static List<LuaCFunctionProxy> _Proxies = new List<LuaCFunctionProxy>();

        LuaCFunctionProxy() { }

        public static LuaCFunctionProxy FindProxy(LuaFunction function)
        {
            if (function == null) return null;
            lock (_Proxies)
            return _Proxies.FirstOrDefault(p => p.ManagedFunction == function);
        }

        public static LuaCFunctionProxy FindProxy(Lua.lua_CFunction function)
        {
            if (function == null) return null;
            lock (_Proxies)
            return _Proxies.FirstOrDefault(p => p.UnmanagedFunction == function);
        }

        public static LuaCFunctionProxy GetProxy(LuaFunction function)
        {
            if (function == null) return null;
            LuaCFunctionProxy result = null;
            result = FindProxy(function);
            if (result == null)
            {
                result = new LuaCFunctionProxy()
                {
                    ManagedFunction = function
                };
                result.UnmanagedFunction = result.InvokeManagementFunction;
                lock (_Proxies)
                    _Proxies.Add(result);
            }
            return result;
        }

        public static LuaCFunctionProxy GetProxy(Lua.lua_CFunction function)
        {
            if (function == null) return null;
            LuaCFunctionProxy result = null;
            result = FindProxy(function);
            if (result == null)
            {
                result = new LuaCFunctionProxy()
                {
                    UnmanagedFunction = function
                };
                result.ManagedFunction = result.InvokeUnmanagedFunction;
                lock (_Proxies)
                    _Proxies.Add(result);
            }
            return result;
        }

        int InvokeUnmanagedFunction(LuaState state)
        {
            LuaState ls = state as LuaState;
            if (UnmanagedFunction != null && ls != null)
            {
                return UnmanagedFunction(ls.NativeState);
            }
            return 0;
        }

        int InvokeManagementFunction(IntPtr state)
        {
            LuaState ls = LuaState.FindState(state, true);
            if (ManagedFunction != null && ls != null)
            {
                return ManagedFunction(ls);
            }
            return 0;
        }

        public LuaFunction ManagedFunction { get; private set; }
        public Lua.lua_CFunction UnmanagedFunction { get; private set; }
    }

}
